package com.ezops.poc.routing;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.activiti.camel.ActivitiProducer;
import org.apache.camel.Body;
import org.apache.camel.Exchange;
import org.apache.camel.Handler;
import org.apache.camel.Header;
import org.apache.camel.Predicate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.converter.jaxb.JaxbDataFormat;
import org.apache.camel.dataformat.csv.CsvDataFormat;
import org.apache.camel.language.Simple;
import org.apache.camel.spi.DataFormat;
import org.springframework.stereotype.Component;

import com.ezops.businessprocess.integration.customtype.Jsonable;
import com.ezops.poc.aggregation.EzopsAggregationStrategy;
import com.ezops.poc.parser.SingleClassBindyCsvDataFormat;
import com.ezops.poc.validations.EzopsValidationException;
import com.ezops.trade.processing.partners.orchestrade.OrchesTradeModel;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Route builder class for configuring the routes in camel context.
 * 
 * @author vishal.gaurav
 * 
 */
@Component(value = "myBuilder")
public class TradeRoutingBuilder extends RouteBuilder {

	public static final String HEADER_KEY_IS_VALID_TRADE = "IS_VALID_TRADE";
	public static final String HEADER_KEY_TRADE_EXCEPTIONS = "TRADE_EXCEPTIONS";
	
	public static ObjectMapper mapper =new ObjectMapper();

	DataFormat jaxb = new JaxbDataFormat(
			"com.ezops.trade.processing.partners.calypsodocument");
	SingleClassBindyCsvDataFormat bindyOtModel = new SingleClassBindyCsvDataFormat();

	Predicate isValidTrade = header(HEADER_KEY_IS_VALID_TRADE).isEqualTo(true);

	/**
	 * COnfigre the routes.
	 */
	public void configure() {

		CsvDataFormat csv = new CsvDataFormat();
		bindyOtModel.setModelClass(OrchesTradeModel.class);

		onException(EzopsValidationException.class).processRef(
				"validationErrorProcessor").continued(true);// to("direct:errors");
		// only trigger when incoming from transformationBean endpoint
		// interceptSendToEndpoint("bean:ezopsFormatConverter?method=convert").to(
		// "direct:persistData");

		// here is a sample which processes the input files
		// (leaving them in place - see the 'noop' flag)
		// then performs content based routing
		from("properties:{{input.path}}").unmarshal(csv)
				.processRef("clientFormatParser").log(body().toString())
				.to("direct:persistData")
				.split(body(), new EzopsAggregationStrategy())
				.to("bean:ezopsFormatConverter?method=convert")
				.processRef("validationProcessor")
				.choice()
					.when(isValidTrade)
						.to("bean:destinationFormatConverter?method=convert").endChoice()
					.otherwise()
						// .to("bean:clientFormatConverter?method=convert")
						.to("direct:createProcess").end()
						.end()//aggregate here
				.processRef("loggingProcessor").to("direct:output");
		// .to("rabbitmq://localhost:5672/Exchange_OrchestradeReportSender?connectionFactory=#customConnectionFactory&queue=Queue_OrchestradeReportCarrier");

		from("direct:output").processRef("splitProcessor");
		CamelActivityHelper helper = new CamelActivityHelper();

		// from("file:/Users/vgaurav/EZOPS/test").unmarshal(csv).processRef("clientFormatParser").split(body())
		// .setBody(bean(helper))
		// .setProperty(PROCESS_KEY_PROPERTY, simple("file:name"))
		// .to("activiti:tradeExceptionProcess")
		// .log("Process to handle incoming order file has been started (process instance id ${body})");

		from("direct:createProcess")
				.setBody(bean(helper))
				.setProperty(ActivitiProducer.PROCESS_KEY_PROPERTY,
						simple("file:name"))
				.to("activiti:tradeExceptionProcess");

		/*
		 * Process the errors
		 */
		from("direct:errors").processRef("clientModelCSVTransformer")
				.marshal(csv).to("properties:{{output.errorpath}}").stop();

		/*
		 * Send valid parsed and converted file to destination.
		 */
		from("direct:validfile").marshal(bindyOtModel).to(
				"properties:{{output.path}}");

		/*
		 * Save the client trade file data.
		 */

		from("direct:persistData").to("bean:clientDAO?method=persist");

		/*
		 * Receive the response from OT.
		 */
		from("properties:{{response.path}}").unmarshal(csv)
				.processRef("otResponseParser").split(body())
				.processRef("OTResponseHandler");
	}

	/*
	 * A few helper methods used for routing
	 */
	public static final class CamelActivityHelper {

		/*
		 * This method will extract information from the Exchange (using Camel
		 * annotations) and put them in a Map that will be used for setting up
		 * the process' variables.
		 */
		@Handler
		public Map getProcessVariables(@Body Object body,
				@Header(Exchange.FILE_NAME) String filename,
				@Header(HEADER_KEY_TRADE_EXCEPTIONS) EzopsValidationException exceptions,
				@Simple("${date:now:yyyy-MM-dd kk:mm:ss}") String timestamp) {
			Map<String, Object> variables = new HashMap<String, Object>();
			
				try {
					variables.put("message", mapper.writeValueAsString(body));
					variables.put("exceptions", mapper.writeValueAsString(exceptions.getFieldErrors()));
				} catch (JsonProcessingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			
			variables.put("filename", filename);
			
			variables.put("timestamp", timestamp);
			return variables;
		}
	}
}
